﻿using System;
using Sirenix.OdinInspector;
using UnityEngine;

#if UNITY_EDITOR
using Sirenix.OdinInspector.Editor;
using UnityEditor;
#endif

namespace Hsenl {
    [DisallowMultipleComponent]
    public class EntityReference : MonoBehaviour, IEntityReference {
        [ShowInInspector]
        private Entity _entity;

        public Entity Entity => this._entity;

        [HideInInspector]
        public int uniqueId;

#if UNITY_EDITOR
        // mono 和 framework的销毁是双向的, 无论谁在销毁时都会把对方也销毁
        private void OnDestroy() {
            var entity = this.Entity;
            if (entity == null)
                return;

            Debug.Log($"做个检测, 要么是编辑器手动销毁, 要么就是不对, 因为框架的销毁一定会在mono销毁之前. '{this.name}'");
            this._entity = null;
            ((IGameObjectReference)entity).SetUnityReference(null);
            Object.Destroy(entity);
        }
#endif

        void IEntityReference.SetFrameworkReference(Entity reference) {
            this._entity = reference;
            if (reference != null) {
                this.uniqueId = reference.uniqueId;
            }
        }

#if UNITY_EDITOR
        // unity的触发条件是一个物体和其下的所有子物体都会触发该事件, 所以用这种方法
        private UnityEngine.Transform tempParent;

        private void OnBeforeTransformParentChanged() {
            this.tempParent = this.transform.parent;
        }

        private void OnTransformParentChanged() {
            if (this.transform.parent == this.tempParent) // 之前的父级和现在的父级一样, 说明自己不是修改的最上层, 就不处理
                return;

            if (this.Entity.setparentinternal) // 该方法只处理从编辑变更父级时的操作, 如果是内部设置的父级, 就不处理了
                return;

            this.Entity.SetParent(this.transform.parent?.GetComponentInParent<EntityReference>()?.Entity);
        }
#endif
    }

#if UNITY_EDITOR
    [CustomEditor(typeof(EntityReference))]
    public class EntityReferenceEditor : OdinEditor {
        private EntityReference _t;

        protected override void OnEnable() {
            base.OnEnable();
            this._t = (EntityReference)this.target;
        }

        public override void OnInspectorGUI() {
            base.OnInspectorGUI();

            var entity = this._t.Entity;
            if (entity == null) {
                return;
            }

            if (entity.Active != this._t.gameObject.activeSelf) {
                entity.Active = this._t.gameObject.activeSelf;
            }

            var parentEntityRef = this._t.transform.parent?.GetComponentInParent<EntityReference>(true);
            var unityTransform1 = parentEntityRef?.transform;
            var unityTransform2 = entity.Parent?.GameObject?.transform;
            if (unityTransform1 != null && unityTransform1 != unityTransform2) {
                entity.SetParent(parentEntityRef.Entity);
            }
        }
    }
#endif
}